#include "DisplayUI.h"

#include "stm32h7xx_hal.h"
#include "stm32h7x_sections.h"
__IN_SECTION_RAM_D1 uint16_t colorBuffer;

void DisplayUI_DrawPixel(uint16_t x, uint16_t y, uint16_t color) {
    SCB_CleanDCache_by_Addr((uint32_t *)&colorBuffer, 32);
    colorBuffer = color;
    Display_FlushArea(DISP_DIR_90_DEG, x, x, y, y, &colorBuffer);
}

void DisplayUI_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) {
    uint16_t tmp;
    if (x1 > x2) {
        tmp = x1;
        x1 = x2;
        x2 = tmp;
    }
    if (y1 > y2) {
        tmp = y1;
        y1 = y2;
        y2 = tmp;
    }

    if ((y2 - y1) >= (x2 - x1)) {
        float dx = (float)(x2 - x1) / (y2 - y1);
        float x = x1;
        uint16_t y = y1;
        do {
            DisplayUI_DrawPixel((uint16_t)x, y, color);
            y += 1;
            x += dx;
        } while (y < y2);
    } else {
        float dy = (float)(y2 - y1) / (x2 - x1);
        float y = y1;
        uint16_t x = x1;
        do {
            DisplayUI_DrawPixel(x, (uint16_t)y, color);
            x += 1;
            y += dy;
        } while (x < x2);
    }
}

void DisplayUI_DrawRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) {
    DisplayUI_DrawLine(x, y, x + w, y, color);
    DisplayUI_DrawLine(x, y, x, y + h, color);
    DisplayUI_DrawLine(x + w, y, x + w, y + h, color);
    DisplayUI_DrawLine(x, y + h, x + w, y + h, color);
}

__IN_SECTION_RAM_D1 uint16_t fillBuffer[512];

void DisplayUI_FillArea(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) {
    uint16_t _y, i;
    for (i = 0; i < 512; i++) fillBuffer[i] = color;
    SCB_CleanDCache_by_Addr((uint32_t *)&fillBuffer, 1024);
    for (_y = y; _y < y + h; _y++) {
        Display_FlushArea(DISP_DIR_90_DEG, x, x + w - 1, _y, _y, fillBuffer);
    }
}

void DisplayUI_DrawChar(uint16_t x, uint16_t y, DisplayFont_Typedef *font, uint16_t bgcolor, uint16_t fgcolor,
                        const char ch) {
    uint16_t fontIndex = (ch - 0x20) * (font->height);
    uint16_t i, j;
    for (i = 0; i < 512; i++) fillBuffer[i] = bgcolor;

    for (i = 0; i < (font->height); i++) {
        uint16_t line = font->data[fontIndex + i];
        for (j = 0; j < (font->width); j++) {
            if ((line << j) & 0x8000) {
                // DisplayUI_DrawPixel(x+j,y+i,color);
                fillBuffer[j] = fgcolor;
            } else {
                fillBuffer[j] = bgcolor;
            }
        }
        SCB_CleanDCache_by_Addr((uint32_t *)&fillBuffer, 1024);
        Display_FlushArea(DISP_DIR_90_DEG, x, x + font->width, y + i, y + i, fillBuffer);
    }
}

void DisplayUI_DrawString(uint16_t x, uint16_t y, DisplayFont_Typedef *font, uint16_t bgcolor, uint16_t fgcolor,
                          const char *str) {
    uint16_t _x = x;
    while (*str != '\0') {
        DisplayUI_DrawChar(_x, y, font, bgcolor, fgcolor, *str);
        _x += font->width;
        str++;
    }
}

void DisplayUI_DrawStringFmt(uint16_t x, uint16_t y, DisplayFont_Typedef *font, uint16_t bgcolor, uint16_t fgcolor,
                             const char *fmt, ...) {
    static char str[256];
    va_list args;
    va_start(args, fmt);
    vsprintf(str, fmt, args);
    DisplayUI_DrawString(x, y, font, bgcolor, fgcolor, str);
}
